/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.suai.system.impl;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.suai.dao.Buffer;
import org.suai.dao.impl.BufferImpl;
import org.suai.dao.impl.PackageImpl;
import org.suai.manager.StatisticManager;
import org.suai.system.QueueSystem;
import org.suai.dao.Package;

/**
 *
 * @author awm
 */
public class BlockSystemImpl implements QueueSystem {
    private int userCount;
    private double intensity;
    private Buffer buffer;
    private List packagesForService;
    private int systemNumber;

    private StatisticManager instance;

    public BlockSystemImpl(int systemNumber, double lamda, int userCount){
        this.systemNumber = systemNumber;
        //buffer  = new BufferAloha();
        buffer = new BufferImpl();
        packagesForService = new ArrayList();
        packagesForService.add(new ArrayList());
        packagesForService.add(new ArrayList());
        instance = StatisticManager.getInstance();
        this.intensity = lamda;
        this.userCount = userCount;
    }

    @Override
    public void setUserCounts(int userCounts) {
        this.userCount = userCounts;
    }

    @Override
    public void setIntensity(double intensity) {
        this.intensity = intensity;
    }

    @Override
    public int getUserCounts() {
        return userCount;
    }

    @Override
    public double getIntensity() {
        return intensity;
    }

    @Override
    public void generatePackages() {
        for(int i = 0; i < userCount; i++) {
            Package item = generatePackage(i);
            if( item != null ) {
                buffer.setPackage(i, item);
                instance.createPackage(this);
            }
        }
    }

    private Package generatePackage(int userNumber) {
        if( !isPackageCreate()) {
            return null;
        }

        return new PackageImpl( systemNumber, userNumber );

    }

    private boolean isPackageCreate() {
        //double p = intensity / (userCount - busyUsers);
        double p = intensity / userCount ;

        if( Math.random() < p ) {
            return true;
        }
        return false;
    }

    @Override
    public List getPackagesForService() {
        return buffer.getPackagesForService();
    }

    @Override
    public void setOuterPackages(List packages) {
        for(int i = 0; i < packages.size(); i++) {
            PackageImpl itemPkg = (PackageImpl)packages.get(i);
            if(!isContains(itemPkg)) {
                List itemList = (List)packagesForService.get(0);
                itemList.add(itemPkg);
                packagesForService.set(0, itemList);
            } 
        }
    }

    private boolean isContains(Package pkg) {
        for(int i = 0; i < packagesForService.size(); i++) {
            List item = (List)packagesForService.get(i);
            if(item.contains(pkg)) {
                return true;
            }
        }

        return false;
    }

    private void servicePackage(Package pkg) {
        if(pkg.getSystemNumber() == this.systemNumber) {
                buffer.servicePackage( pkg.getOwnerNumber() );
                instance.servicePackage(this);
            } else {
                instance.deletePackage(this);
            }
    }

    private List resolveConflict(List packageForService) {
        List result = new LinkedList();
        List level0 = new LinkedList();
        List level1 = new LinkedList();

        double p = 0.5 ;

        for(Object pkg : packageForService.toArray()){
            double rand = Math.random();
            if(rand < p) {
                level0.add(pkg);
            } else {
                level1.add(pkg);
            }
        }

        result.add(level0);
        result.add(level1);
        return result;
    }

    @Override
    public void servicePackages() {
        List level0 = ((List)packagesForService.get(0));
        List level1 = ((List)packagesForService.get(1));

        if(level0 == null) level0 = new ArrayList();
        if(level1 == null) level1 = new ArrayList();

        if(level0.size() == 1) {
            Package pkg = (Package)level0.get(0);
            servicePackage(pkg);
//            level0 = new ArrayList();
//            packagesForService.set(0, level0);

            if(level1.size() == 1) {
                 packagesForService.remove(0);
                 return;
            }

            List resolvePkg = resolveConflict(level1);
            level0 = (List)resolvePkg.get(0);
            level1 = (List)resolvePkg.get(1);

            packagesForService.set(0, level0);
            packagesForService.set(1, level1);

            if(level0.size() == 0)
                packagesForService.remove(0);

            if(packagesForService.size() == 1){
                packagesForService.add(1, new ArrayList());
            }

        } else if (level0.size() > 1) {
            List resolvePkg = resolveConflict(level0);
            packagesForService.remove(0);
            packagesForService.add(0, resolvePkg.get(0));
            if(((List)resolvePkg.get(1)).size() != 0) {
                packagesForService.add(1, resolvePkg.get(1));
            }

            if(level0.size() == 0)
                packagesForService.remove(0);

            if(packagesForService.size() == 1){
                packagesForService.add(1, new ArrayList());
            }
            //packagesForService.add(0, resolvePkg.g);
        } else if (level0.size() == 0) {
            List resolvePkg = resolveConflict(level1);
            packagesForService.set(0, resolvePkg.get(0));
            packagesForService.set(1, resolvePkg.get(1));
        }

    }

    @Override
    public int getSystemNumber() {
        return systemNumber;
    }

}
